package com.molichuxing.baselibrary.net;

import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.widget.TextView;

import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.IOException;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.concurrent.TimeUnit;

/**
 * 网络请求管理
 * 对OkHttp请求进行封装
 */
public class OkHttpManager2 {

    private static OkHttpManager2 instance;
    private OkHttpClient mOkHttpClient;
    private Handler okHandler;

    public OkHttpManager2() {
        mOkHttpClient = new OkHttpClient();
        okHandler = new Handler(Looper.getMainLooper());
        try{
            mOkHttpClient.setConnectTimeout(20, TimeUnit.SECONDS);
        }catch (Exception e){
            e.printStackTrace();
        }
        /**
         * cookie enabled
         * 只接受原始服务器的cookie
         */
//        mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));
    }

    public static OkHttpManager2 getInstance(){
        if(instance==null){
            synchronized(OkHttpManager.class){
                if(instance==null){
                    instance = new OkHttpManager2();
                }
            }
        }
        return instance;
    }

    public void getNet(String url, ResultCallback resultCallback){
        Request request = new Request.Builder()
                .url(url)
                .build();
        dealNet(request,resultCallback);
    }

    public void postNetJson(String url, ResultCallback resultCallback, String json){
        if(TextUtils.isEmpty(json)){
            json = "";
        }
        RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        dealNet(request,resultCallback);
    }

    public void postNet(String url, ResultCallback resultCallback, Param... param){
        if(param == null){
            param = new Param[0];
        }
        FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();
        for(Param p : param){
            formEncodingBuilder.add(p.key,p.value);
        }
        RequestBody requestBody = formEncodingBuilder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        dealNet(request,resultCallback);
    }

    public void upFileNet(String url, ResultCallback resultCallback, File[] files,
                          String[] fileKeys, Param... param){
        Request request = buildMultipartFormRequest(url,files,fileKeys,param);

        dealNet(request,resultCallback);
    }

    private void dealNet(final Request request, final ResultCallback resultCallback){
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(final Request request, final IOException e) {
                okHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        resultCallback.onFailed(request,e);
                    }
                });
            }
            @Override
            public void onResponse(final Response response) {
                String str = "";
                try {
                    str = response.body().string();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                final String finalStr = str;
                okHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        resultCallback.onSuccess(finalStr);
                    }
                });
            }
        });
    }

    private Request buildMultipartFormRequest(String url, File[] files,
                                              String[] fileKeys, Param[] params)
    {
        params = validateParam(params);

        MultipartBuilder builder = new MultipartBuilder()
                .type(MultipartBuilder.FORM);

        for (Param param : params)
        {
            builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + param.key + "\""),
                    RequestBody.create(null, param.value));
        }
        if (files != null)
        {
            RequestBody fileBody = null;
            for (int i = 0; i < files.length; i++)
            {
                File file = files[i];
                String fileName = file.getName();
                fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);
                //根据文件名设置contentType
                builder.addPart(Headers.of("Content-Disposition",
                        "form-data; name=\"" + fileKeys[i] + "\"; filename=\"" + fileName + "\""),
                        fileBody);
            }
        }

        RequestBody requestBody = builder.build();
        return new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
    }

    private Param[] validateParam(Param[] params)
    {
        if (params == null)
            return new Param[0];
        else return params;
    }

    private String guessMimeType(String path)
    {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String contentTypeFor = fileNameMap.getContentTypeFor(path);
        if (contentTypeFor == null)
        {
            contentTypeFor = "application/octet-stream";
        }
        return contentTypeFor;
    }

    public static abstract class ResultCallback{
        public abstract void onFailed(Request request,Exception e);
        public abstract void onSuccess(String response);
    }

    public static class Param{
        String key;
        String value;

        public Param() {
        }

        public Param(String key, String value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public String toString() {
            return "Param{" +
                    "key='" + key + '\'' +
                    ", value='" + value + '\'' +
                    '}';
        }
    }
}
